import * as Router from 'koa-router';
import { resolve } from 'path';
import * as _ from 'lodash';
import * as glob from 'glob';

export let routersMap = new Map();

export const symbolPrefix = Symbol('prefix');

export const isArray = (v:any):Array<any> => _.isArray(v) ? v : [v]
export const normalizePath = (path:string):string => path.startsWith('/') ? path : `/${path}`

export class Route {
  private app:any;
  private apiPath:any;
  private router:any;
  constructor(app:any, apiPath:string) {
    this.app = app;
    this.apiPath = apiPath;
    this.router = new Router()
  }

  init() {
    glob.sync(resolve(this.apiPath, './**/*.js')).forEach(require)

    for(let [ conf, controller ] of routersMap) {
      const controllers = isArray(controller)
      let prefixPath = conf.target[symbolPrefix]
      if (prefixPath) prefixPath = normalizePath(prefixPath)

      const routerPath = prefixPath + conf.path
      this.router[conf.method](routerPath, ...controllers)
    }

    this.app.use(this.router.routes())
    this.app.use(this.router.allowedMethods())
  }
}

export const controller = (path:string) => (target:Function) => {target.prototype[symbolPrefix] = path}

export const router = (conf:any) => (target:any, key:any, desc:any) => {
  conf.path = normalizePath(conf.path)

  routersMap.set({
    target: target,
    ...conf
  }, target[key])
}

export const get = (path:string) => router({
  method: 'get',
  path: path
})

export const post = (path:string) => router({
  method: 'post',
  path: path
})

export const put = (path:string) => router({
  method: 'put',
  path: path
})

export const del = (path:string) => router({
  method: 'del',
  path: path
})

